﻿using System;
using System.Collections.Generic;
using System.Threading;
using System.Windows.Forms;
using S7.Net;
using S7PlcDataManager.S7Plc;
using S7PlcDataManager.S7Plc.Types;
using S7PlcDataManager.Tools;
using ZbSkin.Frm;
using ZbSkin.Tools;

namespace S7PlcDataManager.Controls
{
    public partial class ConnectControl : UserControl
    {
        private readonly SynchronizationContext _context;
        private readonly S7PlcHelper _s7PlcHelper;

        public ConnectControl(S7PlcHelper s7PlcHelper)
        {
            InitializeComponent();

            _context = SynchronizationContext.Current;
            _s7PlcHelper = s7PlcHelper;

            Disposed += ConnectControl_Disposed;
        }

        private void ConnectControl_Load(object sender, EventArgs e)
        {
            var plcTypeList = new List<PlcType>()
            {
                new PlcType {Type = CpuType.S7200, TypeString = @"S7-200"},
                new PlcType {Type = CpuType.S7300, TypeString = @"S7-300"},
                new PlcType {Type = CpuType.S7400, TypeString = @"S7-400"},
                new PlcType {Type = CpuType.S71200, TypeString = @"S7-1200"},
                new PlcType {Type = CpuType.S71500, TypeString = @"S7-1500"}
            };
            cmb_type.DataSource = plcTypeList;
            cmb_type.DisplayMember = "TypeString";
            cmb_type.SelectedIndex = plcTypeList.Count - 1;

            tb_ip.Text = Constants.S7PlcServerIp;
            tb_port.Text = Constants.S7PlcServerPort.ToString();
            tb_rack.Text = Constants.S7PlcServerRack.ToString();
            tb_slot.Text = Constants.S7PlcServerSlot.ToString();

            EnableConnButton(true);

            SetRegion();
        }

        private void ConnectControl_Disposed(object sender, EventArgs e)
        {
            try
            {
                _s7PlcHelper.Close();
                _s7PlcHelper.UnInit();
            }
            catch (Exception exception)
            {
                LogHelper.AddErrorLog(exception.Message);
            }
        }

        private void ConnectControl_Resize(object sender, EventArgs e)
        {
            SetRegion();
        }

        private void SetRegion()
        {
            this.SetRegion(30);
        }

        private void btn_conn_Click(object sender, EventArgs e)
        {
            string ip;
            int port;
            short rack;
            short slot;
            if (!CheckParas(out ip, out port, out rack, out slot))
            {
                return;
            }

            EnableConnButton(false);
            btn_disconn.Enabled = false;
            pictureBox_loading.Visible = true;

            var cpuType = (cmb_type.SelectedItem as PlcType)?.Type ?? CpuType.S71500;
            ConnectPlc(cpuType, ip, port, rack, slot);
        }

        // ReSharper disable once IdentifierTypo
        private void btn_disconn_Click(object sender, EventArgs e)
        {
            _s7PlcHelper.Close();
            _s7PlcHelper.UnInit();

            EnableConnButton(true);
        }

        private bool CheckParas(out string ip, out int port, out short rack, out short slot)
        {
            port = 0;
            rack = 0;
            slot = 0;

            ip = tb_ip.Text.Trim();
            if (string.IsNullOrWhiteSpace(ip))
            {
                MessageBoxEx.Warning(@"请输入PLC IP地址", ParentForm);
                return false;
            }

            var portString = tb_port.Text.Trim();
            if (string.IsNullOrWhiteSpace(portString))
            {
                MessageBoxEx.Warning(@"请输入PLC端口", ParentForm);
                return false;
            }

            if (!int.TryParse(portString, out port))
            {
                MessageBoxEx.Warning(@"PLC端口有误", ParentForm);
                return false;
            }

            var rackString = tb_rack.Text.Trim();
            if (string.IsNullOrWhiteSpace(rackString))
            {
                MessageBoxEx.Warning(@"请输Rack", ParentForm);
                return false;
            }

            if (!short.TryParse(rackString, out rack))
            {
                MessageBoxEx.Warning(@"Rack有误", ParentForm);
                return false;
            }

            var slotString = tb_slot.Text.Trim();
            if (string.IsNullOrWhiteSpace(rackString))
            {
                MessageBoxEx.Warning(@"请输Slot", ParentForm);
                return false;
            }

            if (!short.TryParse(slotString, out slot))
            {
                MessageBoxEx.Warning(@"Slot有误", ParentForm);
                return false;
            }

            return true;
        }

        private void ConnectPlc(CpuType cpuType, string ip, int port, short rack, short slot)
        {
            _s7PlcHelper.UnInit();
            _s7PlcHelper.Init(cpuType, ip, port, rack, slot);
            var taskAwaiter = _s7PlcHelper.OpenAsync(default(CancellationToken)).GetAwaiter();
            taskAwaiter.OnCompleted(() =>
            {
                _context?.Post((state) =>
                {
                    pictureBox_loading.Visible = false;
                    EnableConnButton(!_s7PlcHelper.IsConnected);
                    if (!_s7PlcHelper.IsConnected)
                    {
                        MessageBoxEx.Warning($@"连接PLC[{_s7PlcHelper.Ip}]失败", ParentForm);
                    }
                }, null);
            });
        }

        private void EnableConnButton(bool enable)
        {
            cmb_type.Enabled = enable;
            tb_ip.Enabled = enable;
            tb_port.Enabled = enable;
            tb_rack.Enabled = enable;
            tb_slot.Enabled = enable;
            btn_conn.Enabled = enable;
            btn_disconn.Enabled = !enable;
        }
    }
}
